import json
import base64
from hashlib import md5
from .aes_tool import AesTool

class FooderAuthenticationError(RuntimeError):
    def __init__(self, errMsg):
        self.errMsg = errMsg

    def data(self, errDetails):
        self.errDetails = errDetails
        return self

ErrServerTokenNull = FooderAuthenticationError("未检测到Access_token")
ErrServerTokenParse = FooderAuthenticationError("Access_token解析失败")
ErrServerTokenPackage = FooderAuthenticationError("Access_token组成规则没有冒号")
ErrServerUnauthorized = FooderAuthenticationError("Access_token设备未授权")
ErrServerTokenBody = FooderAuthenticationError("body内容被篡改")

def filter(event, aeskey, LOCAL, foodRedis):
    '''
    统一接口鉴权
    返回值：解析的body体<class dict>, shopId终端设备唯一标识<class str>
    '''
    if LOCAL:
        with open('event.evt', 'r') as f:
            event = f.read()
    # 解析event参数
    evt_list = json.loads(event)
    # 解析header
    headers = evt_list['headers']
    if 'Access_token' not in headers:
        raise ErrServerTokenNull

    # 解析Access_token
    aes_token = headers['Access_token']
    aes = AesTool(aeskey, aeskey)
    try:
        token_parse = aes.decode(aes_token)
    except Exception as e:
        raise ErrServerTokenParse.data(str(e))

    # Access_token生成规则：AES(shopId:md5(body))
    if ':' not in token_parse:
        raise ErrServerTokenPackage

    # 解析 shopId 与 md5(body)
    tokens = token_parse.split(':')
    deviceId = tokens[0]
    md5body = tokens[1]
    # Redis中确定设备是否被运维平台授权，根据deviceId查询shopId
    shopId = foodRedis.get_shopId_device(deviceId)
    if shopId is None:
        raise ErrServerUnauthorized.data(f'deviceId={deviceId}未找到shopId')

    # 解析base64编码的body
    isbase64 = evt_list['isBase64Encoded']
    if isbase64:
        body = base64.b64decode(evt_list['body'])
    else:
        body = evt_list['body']
    # 计算body的md5
    # body=b'xxx', type=<class 'bytes'> --> body.decode() 默认为utf8编码转为string
    bodymd5 = md5(body.decode().encode('utf-8')).hexdigest()
    if md5body.lower() != bodymd5.lower():
        raise ErrServerTokenBody.data(f'deviceId={deviceId}body体被篡改')

    # 解析 body json
    j_data = json.loads(body)
    return j_data, shopId
